"""
CSPBuilder plugin

Provides icon functionality

Copyright (c) 2008 Rune M. Friborg, runef@diku.dk.
See LICENSE.txt for licensing details (GPLv2).
"""

PLUGIN_NAME = "Process Icon"

import base64
import cStringIO
try:
    import cPickle as pickle
except:
    import pickle

import wx
import os

from plugins.builder import *


class PluginIcon(PluginBUILDER):

    def __init__(self, pluginManager):
        PluginBUILDER.__init__(self, pluginManager, PLUGIN_NAME)

        self.white_png =  'UyJceDg5UE5HXHJcblx4MWFcblx4MDBceDAwXHgwMFxySUhEUlx4MDBceDAwXHgwMEBceDAwXHgwMFx4MDBAXHgwOFx4MDJceDAwXHgwMFx4MDAlXHgwYlx4ZTZceDg5XHgwMFx4MDBceDAwXHgwMXNSR0JceDAwXHhhZVx4Y2VceDFjXHhlOVx4MDBceDAwXHgwMFx0cEhZc1x4MDBceDAwXHgwYlx4MTNceDAwXHgwMFx4MGJceDEzXHgwMVx4MDBceDlhXHg5Y1x4MThceDAwXHgwMFx4MDBceDA3dElNRVx4MDdceGQ4XHRceDE5XG4jOVx4ZmVceDgzNDlceDAwXHgwMFx4MDBceDE5dEVYdENvbW1lbnRceDAwQ3JlYXRlZCB3aXRoIEdJTVBXXHg4MVx4MGVceDE3XHgwMFx4MDBceDAwTUlEQVRoXHhkZVx4ZWRceGNmQVxyXHgwMFx4MDBceDA4XHgwNCBceGI1XHg3Zlx4ZTczXHg4NVx4MGY3aEAnXHhhOVx4Y2ZceGE2XHg5ZVx4MTNceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceDEwXHgxMFx4MTBceGI4XHhiN3JceGFhXHgwM31eXHhkOWNceDllXHgwMFx4MDBceDAwXHgwMElFTkRceGFlQmBceDgyIgpwMQou'

        # Wx Items
        self.iconCtrl = None
        self.infoIconCtrl = None
        self.deleteButton = None
        self.iconPanel = None
        

    def _check_icon(self, icon):
        return (icon != None and icon != '')


    def _draw_controls(self, mainFrame):

        self.iconPanel = wx.Panel(mainFrame.leftPanel, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)

        self.iconPanel.SetAutoLayout(True)
        self.iconPanel.SetSizer(sizer)

        leftSizer = mainFrame.leftPanel.GetSizer()
        leftSizer.Add(self.iconPanel)

        sizer.Add(wx.StaticText(self.iconPanel, -1, "Icon:") , 0, wx.ALL, 5 ) 
        self.deleteButton = wx.Button(self.iconPanel, 10, "Delete", (20, 20))
        self.deleteButton.Bind(wx.EVT_BUTTON,  lambda event:self._clear_icon(mainFrame,event), self.deleteButton)

        self._update_icon(mainFrame)

        sizer.Add(self.deleteButton, 0, wx.ALIGN_RIGHT | wx.TOP | wx.BOTTOM, 5)


    def _update_icon(self, mainFrame):

        # Show icon if available
        iconData = ''
        if (mainFrame.plugin_attr.has_key('icon') and mainFrame.plugin_attr['icon'] != ''):
            iconData = mainFrame.plugin_attr['icon']
            self.deleteButton.Enable(1)
        else:
            # White png 64x64
            iconData = self.white_png
            self.deleteButton.Enable(0)
        width = 105
        imgData = pickle.loads(base64.b64decode(iconData))
        imgStream = cStringIO.StringIO(imgData)
        img = wx.ImageFromStream(imgStream)
        ratio = float(img.GetHeight()) / float(img.GetWidth())
        height = int(ratio*width)
        img.Rescale(width, height, quality=wx.IMAGE_QUALITY_HIGH)

        icon = wx.StaticBitmap(self.iconPanel, -1, img.ConvertToBitmap(), (330,280), (width,height),style=wx.SUNKEN_BORDER)
        icon.Bind(wx.EVT_LEFT_DOWN, lambda event:self._change_icon(mainFrame,event))
        sizer = self.iconPanel.GetSizer()
        if (self.iconCtrl != None):
            sizer.Replace(self.iconCtrl, icon)
            # Destroy old
            self.iconCtrl.Destroy()
        else:
            sizer.Add(icon, 0, wx.LEFT, 15)

        # Add new
        self.iconCtrl = icon

        sizer.Fit(self.iconPanel)

    def _clear_icon(self, mainFrame, evt):

        mainFrame.plugin_attr['icon'] = ''
        self._update_icon(mainFrame)


    def _change_icon(self, mainFrame, evt):

        wildcard = "PNG (*.png)|*.png|"     \
            "All files (*.*)|*.*"

        saveDir = os.getcwd()

        dlg = wx.FileDialog(
            mainFrame.leftPanel, message="Choose an icon file",
            defaultDir=os.getcwd(),
            defaultFile="",
            wildcard=wildcard,
            style=wx.OPEN | wx.CHANGE_DIR
            )

        if dlg.ShowModal() == wx.ID_OK:
            # This returns a Python list of files that were selected.
            paths = dlg.GetPaths()

            f = open(paths[0], 'r')
            s = f.read()
            f.close()
            mainFrame.plugin_attr['icon'] = base64.b64encode(pickle.dumps(s))

            self._update_icon(mainFrame)

        dlg.Destroy()

        os.chdir(saveDir)



    def _draw_fix_size(self, dc, obj, position, selected):
        attr = obj.plugin_attr

        # If has icon, then set size of process to icon size
        if (attr.has_key('icon') and attr['icon'] != ''):
            imgData = pickle.loads(base64.b64decode(attr['icon']))
            imgStream = cStringIO.StringIO(imgData)
            img = wx.ImageFromStream(imgStream)
            obj.size.width = img.GetWidth() + 10
            obj.size.height = img.GetHeight() + 10


    def _draw_icon(self, dc, obj, position, selected):
        attr = obj.plugin_attr

        # If has icon, then set size of process to icon size
        if (attr.has_key('icon') and attr['icon'] != '' and not selected):
            imgData = pickle.loads(base64.b64decode(attr['icon']))
            imgStream = cStringIO.StringIO(imgData)
            img = wx.ImageFromStream(imgStream)
            obj.size.width = img.GetWidth() + 10
            obj.size.height = img.GetHeight() + 10

            dc.DrawBitmap(img.ConvertToBitmap(), position.x + 5, position.y + 5, True)


    def _draw_component_info(self, dialog, componentObj):

        # Remove icon if any
        if (self.infoIconCtrl != None):
            self.infoIconCtrl.Destroy()
            self.infoIconCtrl = None

        # Show icon if available
        if (componentObj.plugin_attr.has_key('icon') and componentObj.plugin_attr['icon'] != ''):
            width = 105
            imgData = pickle.loads(base64.b64decode(componentObj.plugin_attr['icon']))
            imgStream = cStringIO.StringIO(imgData)
            img = wx.ImageFromStream(imgStream)
            ratio = float(img.GetHeight()) / float(img.GetWidth())
            height = int(ratio*width)
            img.Rescale(width, height)
            self.infoIconCtrl = wx.StaticBitmap(dialog, -1, img.ConvertToBitmap(), (315,280), (width,height), style=wx.SUNKEN_BORDER)



def load(pluginManager):

    p = PluginIcon(pluginManager)

    p.addCSPAttribute(node_PROCESS_CONTAINER, 'icon', str, '', p._check_icon)
    p.addLeftBarElement(p._draw_controls)
    p.addDrawElement(location_PROCESS, 1, p._draw_fix_size)
    p.addDrawElement(location_PROCESS, 3, p._draw_icon)
    p.addComponentInfoElement(p._draw_component_info)

    pluginManager.addPlugin(p)
